/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_SIP_H
#define MK_SIP_H
#include "MkSipTransaction.h"
#include "MkSipDialog.h"
#include "MkSipListener.h"
#include "MkUtil/MkRwLock.h"

typedef MkFunction<void(const MkSipStatus& Status, const MkMapString& ExternHeaders, const MkSipContentType& ContentType, const MkString& ResBody)> EventRequestCallback;
typedef MkFunction<void(const MkMapString& ExternHeaders, const MkString& ResBody)> EventResponseCallback;

class CMkEventPool;
class CMkTimer;
class CMkSipUdpListener;
class CMkSipTcpSession;
class CMkSipTcpListener;
class MkApi CMkSipServer
{
public:
    CMkSipServer(CMkEventPool* pEventPool, CMkTimer* pTimer);
    virtual ~CMkSipServer();

    Uint32 Start(const MkString& SipId, const MkString& Realm, const MkString& UdpListenHost, Uint16 UdpListenPort, const MkString& UdpPublicHost = "", Uint16 UdpPublicPort = 0, const MkString& TcpListenHost = "", Uint16 TcpListenPort = 0, const MkString& TcpPublicHost = "", Uint16 TcpPublicPort = 0);
    Uint32 Stop();

    CMkEventPool* GetEventPool() { return m_pEventPool; }
    CMkTimer* GetTimer() { return m_pTimer; }
    const MkString& GetRealm() const { return m_Realm; }
    const MkString& GetSipId() const { return m_SipId; }
    void SetRealm(const MkString& Realm) { m_Realm = Realm; }
    void SetSipId(const MkString& SipId) { m_SipId = SipId; }
    void SetUdpPublicHost(const MkString& PublicHost);
    void SetUdpPublicPort(const Uint16& PublicPort);
    void SetTcpPublicHost(const MkString& PublicHost);
    void SetTcpPublicPort(const Uint16& PublicPort);
    const MkString& GetUdpPublicHost() const;
    const MkString& GetTcpPublicHost() const;
protected:
    Uint32 StopCall(const MkString& CallId, const SipMsgCompleteCallback& Cb);
    Uint32 StopSubscribe(const MkString& SubscribeId, const MkMapString& ExtendHeaders, const SipMsgCompleteCallback& Cb);
    Uint32 Register(const MkString& RegisterId, const MkMapString& ExternHeader, const SipMsgCompleteCallback& Cb);
    Uint32 SubscribeNotify(const MkString& SubscribeId, const MkString& strEvent, const MkString& State, const MkMapString& StateExpend, const MkSipContentType& ContentType, const MkString& ContentBody, const SipMsgCompleteCallback& Cb);
    Uint32 CallInfo(const MkString& CallId, const MkSipContentType& ContentType, const MkString& ContentBody, const SipMsgCompleteCallback& Cb);
    Uint32 CallMessage(const MkString& CallId, const MkSipContentType& ContentType, const MkString& ContentBody, const SipMsgCompleteCallback& Cb);

    Uint32 SendSipRequest(const MkString& SipId, const MkString& DstId, const MkString& SipRealm, const MkSipMethod& Method, const MkString& RemoteHost, Uint16 RemotePort, BOOL bTcp, const SipMsgCompleteCallback& Cb, const MkMapString& OtherHeader = MkMapString(), const MkSipContentType& ContentType = MkSipContentNone, const MkString& ContentBody = "", const MkString& DiscribeName = "");

    //mast call event call back
    virtual Uint32 OnSipRequest(const MkSipRequestEvent& RequestEvent, const CMkSipMessage& SipRequest, const EventRequestCallback& Cb) = 0;
    virtual Uint32 OnSipResponse(const MkSipResponseEvent& ResponseEvent, const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const EventResponseCallback& Cb) = 0;
private:
    Uint32 OnSipBufferRecved(const Uint8* pBuf, Uint32 nLen, const MkString& RemoteHost, Uint16 RemotePort, const MkString& LocalHost, Uint16 LocalPort, BOOL bTcp, Uint32& nUsed);
    friend CMkSipUdpListener;
    friend CMkSipTcpListener;
    Uint32 OnRecvSipMessage(const CMkSipMessage& SipMessage);
    Uint32 OnRecvSipRequest(const CMkSipMessage& SipMessage);
    Uint32 OnRecvSipResponse(const CMkSipTransaction& Transaction);
    Uint32 OnTransactionTimer();
private:
    Uint32 SendDialogMessage(const MkString& DialogId, const MkSipMethod& Method, const SipMsgCompleteCallback& Cb, const MkSipContentType& ContentType = MkSipContentNone, const MkMapString& OtherHeader = MkMapString(), const MkString& ContentBody = "");
    Uint32 SendAck(const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const MkMapString& ExtenHeader, const MkString& ContentBody, CMkSipMessage& SipAck);
    Uint32 SendSipResponse(const CMkSipMessage& SipRequest, const MkSipStatus& StatusCode, const MkMapString& OtherHeader = MkMapString(), const MkSipContentType& ContentType = MkSipContentNone, const MkString& ContentBody = "");

    Uint32 SendRefreshSubscribe(const MkString& SubId);
    Uint32 SendRefreshRegister(const MkString& RegId);

    Uint32 UpdateTransaction(const CMkSipMessage& SipMsg, CMkSipTransaction& Transaction);
    Uint32 AddSipMessageToTransaction(const CMkSipMessage& SipMsg, BOOL bCallee = FALSE);
    Uint32 DeleteTransaction(const MkString& TransId);

    Uint32 AddDialog(const CMkSipMessage& Request, const CMkSipMessage& Response, const CMkSipMessage& Ack, const CMkSipDialog::MkSipCallType& CallType);
    Uint32 GetDialog(const MkString& DailogId, CMkSipDialog& Dailog);
    Uint32 DeleteDialog(const MkString& DailogId);
    Uint32 ResendTransaction(const CMkSipTransaction& Transaction);
    Uint32 PacketVia(const CMkSipMessage& SipRequest, CMkSipVia& Via);

    Uint32 SendSipMessage(const CMkSipMessage& SipMessage, const SipMsgCompleteCallback& Cb = nullptr, BOOL bResend = FALSE);
private:
    CMkEventPool*                           m_pEventPool;
    CMkTimer*                               m_pTimer;
    MkString                                m_SipId;
    MkString                                m_Realm;
    MkString                                m_TranactionCheckTimer;
    Uint32                                  m_SipSeqNo;

    CMkSipTcpListener*                      m_pTcpListener;
    CMkSipUdpListener*                      m_pUdpListener;

    CMkRwLock                               m_TranactionLock;
    MkMap<MkString, CMkSipTransaction>      m_MapTranaction;  //key sip message transaction id

    CMkRwLock                               m_DialogLock;
    MkMap<MkString, CMkSipDialog>           m_MapDialog;  //key sip call-id
};




#endif